package audio

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"log"
	"moko/internal/response"
	"net/http"
	"sync"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/gorilla/websocket"
	"mime/multipart"
)

// Client 用于存储WebSocket连接，以client_id为键，连接对象为值
type Client struct {
	ID   string
	Conn *websocket.Conn
}

var (
	connections = make(map[string]*Client)
	mu          sync.Mutex
)

// 用于升级HTTP连接为WebSocket连接的配置
var upgrader = websocket.Upgrader{
	// 允许跨域请求，实际应用中可按需调整更严格的跨域策略
	CheckOrigin: func(r *http.Request) bool {
		return true
	},
}

// HandleWebSocket 处理WebSocket连接的函数，接收client_id参数
func HandleWebSocket(c *gin.Context) {
	clientID := c.Query("client_id")

	if clientID == "" {
		log.Println("缺少client_id参数")
		c.JSON(400, gin.H{"error": "缺少client_id参数"})
		return
	}

	// 将HTTP连接升级为WebSocket连接
	conn, err := upgrader.Upgrade(c.Writer, c.Request, nil)
	if err != nil {
		log.Println("升级WebSocket连接失败:", err)
		return
	}
	defer conn.Close()

	// 将新连接添加到connections字典中，以client_id作为键
	client := &Client{ID: clientID, Conn: conn}
	mu.Lock()
	connections[clientID] = client
	mu.Unlock()
	log.Printf("客户端 %s 已连接，当前连接数: %d\n", clientID, len(connections))

	for {
		conn.SetReadDeadline(time.Now().Add(180 * time.Second))
		_, msgJson, err := conn.ReadMessage()
		if err != nil {
			if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway, websocket.CloseAbnormalClosure) {
				log.Printf("客户端 %s 读取消息出错: %s\n", clientID, err)
			}
			// 移除断开连接的客户端记录
			mu.Lock()
			delete(connections, clientID)
			mu.Unlock()
			log.Printf("客户端 %s 已断开连接，当前连接数: %d\n", clientID, len(connections))
			break
		}
		fmt.Printf("收到客户端 %s 消息: %s\n", clientID, string(msgJson))

		// 解析json参数
		type msgStruct struct {
			Data string `json:"data"`
			Type string `json:"type"`
		}

		var MsgRes msgStruct
		err = json.Unmarshal(msgJson, &MsgRes)

		log.Printf("type: %s\n", MsgRes.Type)
		log.Printf("data: %s\n", MsgRes.Data)

		if MsgRes.Type != "ping" {
			// 将消息以 multipart/form-data 形式发送到目标接口
			respBody, err := forwardMessageToTarget([]byte(MsgRes.Data))
			if err != nil {
				log.Printf("转发消息到目标接口失败: %s\n", err)
				// 向客户端发送错误信息
				errMsg := []byte(fmt.Sprintf("转发消息失败: %s", err.Error()))
				err = conn.WriteMessage(websocket.TextMessage, errMsg)
				if err != nil {
					log.Printf("客户端 %s 回复消息失败: %s\n", clientID, err)
					break
				}
				continue
			}

			// 解码 JSON 响应到结构体
			var MsgRes response.TextReport
			err = json.Unmarshal(respBody, &MsgRes)
			if err != nil {
				log.Printf("解码 JSON 响应失败: %s\n", err)
				errMsg := []byte(fmt.Sprintf("解码 JSON 响应失败: %s", err.Error()))
				err = conn.WriteMessage(websocket.TextMessage, errMsg)
				if err != nil {
					log.Printf("客户端 %s 回复消息失败: %s\n", clientID, err)
					break
				}
				continue
			}

			replayMsg := MsgRes.ResultText

			// 向客户端回复目标接口的响应
			err = conn.WriteMessage(websocket.TextMessage, []byte(replayMsg))
			if err != nil {
				log.Printf("客户端 %s 回复消息失败: %s\n", clientID, err)
				break
			}
		}
	}
}

// forwardMessageToTarget 将消息以 multipart/form-data 形式发送到目标接口并返回响应
func forwardMessageToTarget(msg []byte) ([]byte, error) {
	// 创建一个缓冲区来存储 multipart/form-data 请求体
	body := &bytes.Buffer{}

	// 创建 multipart writer
	writer := multipart.NewWriter(body)

	// 创建文本字段
	err := writer.WriteField("message", string(msg))
	if err != nil {
		return nil, fmt.Errorf("创建文本字段失败: %w", err)
	}

	// 关闭 writer 以完成 multipart/form-data 请求体的构建
	err = writer.Close()
	if err != nil {
		return nil, fmt.Errorf("关闭 multipart writer 失败: %w", err)
	}

	// 创建HTTP请求
	req, err := http.NewRequest("POST", "http://59.110.90.37:8057/text/", body)
	if err != nil {
		return nil, fmt.Errorf("创建请求失败: %w", err)
	}

	// 设置请求头
	req.Header.Set("Content-Type", writer.FormDataContentType())

	// 打印请求头和请求体（仅用于调试）
	//log.Printf("请求头: %v\n", req.Header)
	//log.Printf("请求体: %s\n", body.String())

	// 发送请求
	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		return nil, fmt.Errorf("发送请求失败: %w", err)
	}
	defer resp.Body.Close()

	// 读取响应内容
	respBody, err := io.ReadAll(resp.Body)
	if err != nil {
		return nil, fmt.Errorf("读取响应失败: %w", err)
	}

	// 检查响应状态码
	if resp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("目标接口返回错误状态码: %d, 响应: %s", resp.StatusCode, string(respBody))
	}

	return respBody, nil
}

// SendMessageToClient 向特定客户端发送消息
func SendMessageToClient(clientID string, message []byte) error {
	mu.Lock()
	client, exists := connections[clientID]
	mu.Unlock()
	if !exists {
		return fmt.Errorf("客户端 %s 不存在", clientID)
	}

	err := client.Conn.WriteMessage(websocket.TextMessage, message)
	if err != nil {
		log.Printf("向客户端 %s 发送消息失败: %s\n", clientID, err)
		return err
	}
	return nil
}

// BroadcastMessage 向所有客户端发送消息
func BroadcastMessage(message []byte) {
	mu.Lock()
	defer mu.Unlock()
	for _, client := range connections {
		err := client.Conn.WriteMessage(websocket.TextMessage, message)
		if err != nil {
			log.Printf("向客户端 %s 发送消息失败: %s\n", client.ID, err)
			// 移除断开连接的客户端记录
			delete(connections, client.ID)
		}
	}
}
